package com.ak.es.utils;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * @program: AK-ES
 * @description: 类对象操作工具类
 * @author: AK
 * @create: 2019-01-23 11:49
 **/
public class BeanTools {
	public static Object mapToObject(Map<Object, Object> map, Class<?> beanClass) throws Exception {
		if (map == null)
			return null;

		Object obj = beanClass.newInstance();

		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			if (map.get(field.getName()) == null || StringUtils.isEmpty(map.get(field.getName()))) {
				continue;
			}
			int mod = field.getModifiers();
			if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
				continue;
			}
			field.setAccessible(true);
			field.set(obj, map.get(field.getName()));
		}
		return obj;
	}

	public static Map<String, Object> objectToMap(Object obj) throws Exception {
		if (obj == null) {
			return null;
		}
		Map<String, Object> map = new HashMap<>();
		Field[] declaredFields = obj.getClass().getDeclaredFields();
		for (Field field : declaredFields) {
			field.setAccessible(true);
			map.put(field.getName(), field.get(obj));
		}

		return map;
	}

	@SuppressWarnings("rawtypes")
	public static String[] getNoValuePropertyNames(Object source) {
		Assert.notNull(source, "传递的参数对象不能为空");
		final BeanWrapper beanWrapper = new BeanWrapperImpl(source);
		PropertyDescriptor[] pds = beanWrapper.getPropertyDescriptors();

		Set<String> noValuePropertySet = new HashSet<>();
		Arrays.stream(pds).forEach(pd -> {
			Object propertyValue = beanWrapper.getPropertyValue(pd.getName());
			if (StringUtils.isEmpty(propertyValue)) {
				noValuePropertySet.add(pd.getName());
			} else {
				if (Iterable.class.isAssignableFrom(propertyValue.getClass())) {
					Iterable iterable = (Iterable) propertyValue;
					Iterator iterator = iterable.iterator();
					if (!iterator.hasNext())
						noValuePropertySet.add(pd.getName());
				}
				if (Map.class.isAssignableFrom(propertyValue.getClass())) {
					Map map = (Map) propertyValue;
					if (map.isEmpty())
						noValuePropertySet.add(pd.getName());
				}
			}
		});
		String[] result = new String[noValuePropertySet.size()];
		return noValuePropertySet.toArray(result);
	}
}
